package optimizers.ganeat;

import java.io.Serializable;
import java.util.ArrayList;

public class Species implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public Individual representative;
	public ArrayList<Individual> individuals;
	private int nextGenPopulation = 0;

	public Species(Individual representative) {
		this.representative = representative;
		this.individuals = new ArrayList<Individual>();
	}

	public double getTotalFitness() {
		double totalFitness = 0;
		for (Individual i : individuals) {
			totalFitness += i.getFitness();
		}
		return totalFitness;
	}

	public Individual getBestIndividual() {
		Individual bestIndividual = individuals.get(0);
		for (Individual indiv : individuals) {
			if (indiv.getFitness() > bestIndividual.getFitness()) {
				bestIndividual = indiv;
			}
		}
		return bestIndividual;
	}

	public String getName() {
		return this.representative.generationIndex + ","
				+ this.representative.individualIndex;
	}

	@Override
	public String toString() {
		String result = "Species representative: "
				+ this.representative.generationIndex + ","
				+ this.representative.individualIndex + "\n";
		result += "Population: " + this.individuals.size() + "\n";
		result += "Species fitness: " + this.getSpeciesFitness() + "\n";
		result += "Fitness's Standard deviation: "
				+ this.getStandardDeviation() + "\n";
		result += "Next gen population: " + this.getNextGenPopulation() + "\n";
		return result;
	}

	private double getStandardDeviation() {
		double result = 0;
		double speciesFitness = getSpeciesFitness();
		for (Individual indiv : individuals) {
			result += (indiv.getFitness() - speciesFitness)
					* (indiv.getFitness() - speciesFitness);
		}
		return result / individuals.size();
	}

	public double getSpeciesFitness() {
		double result = 0;
		for (Individual indiv : individuals) {
			result += indiv.getFitness();
		}
		return result / individuals.size();
	}

	public int getNextGenPopulation() {
		return nextGenPopulation;
	}

	public void setNextGenPopulation(int nextGenPopulation) {
		this.nextGenPopulation = nextGenPopulation;
	}
}
